package iscte.iul.dcti.pa2013_14.sqlib;
import java.lang.reflect.Field;
import java.util.*;


public  class SQLGenerator {

	
	public void setMapper(DataMapper mapper) {
		this.mapper = mapper;
	}
	public String createTableInstruction(Class<?> c) {
		String sql = "CREATE TABLE " + mapper.formatSqlcommand(c.getSimpleName()) + "(";
		Field[] fields = c.getDeclaredFields();
		
		for(int i = 0; i < fields.length; i++) {
			if(i != 0)
				sql += ",";
			sql += fields[i].getName() + " " + mapper.convertType(fields[i].getType());
			
			if(i == 0)
				sql += " PRIMARY KEY";		
		}
		
		sql += ",";
		for(int i = 0; i < fields.length; i++) {
			
			//debug
			Class<?> classe = fields[i].getType();
			
			int debug = 0;
			
			if (!classe.isPrimitive() && classe != java.lang.String.class && !isWrapperType(classe)) {	//implementa outra classe, logo é FK
				sql += "\nCONSTRAINT fk_" + fields[i].getName() + " FOREIGN KEY " + fields[i].getName() + "\nREFERENCES " + fields[i].getDeclaringClass().getSimpleName() + "(" + fields[i].getDeclaringClass().getDeclaredFields()[0].getName() + ")";
			}
		}
		
		
		sql += ");";
		
		return sql;
	}

	
	public static boolean isWrapperType(Class<?> clazz)
    {
        return WRAPPER_TYPES.contains(clazz);
    }

    private static Set<Class<?>> getWrapperTypes()
    {
        Set<Class<?>> ret = new HashSet<Class<?>>();
        ret.add(Boolean.class);
        ret.add(Character.class);
        ret.add(Byte.class);
        ret.add(Short.class);
        ret.add(Integer.class);
        ret.add(Long.class);
        ret.add(Float.class);
        ret.add(Double.class);
        ret.add(Void.class);
        return ret;
    }
	
	
	public String updateTableInstruction(Class<?> c) {
		String sql = "UPDATE " + c.getSimpleName() + " SET ";		
		Field[] fields = c.getDeclaredFields();
		
		for (int i = 0; i < fields.length; i++) {
			if (i != 0) {
				sql += ",";				
			}
			sql += fields[i].getName() + " = 'TODO'"; 
		}		
		return sql;
	}
	
//	private String convertType(Class<?> type) {
//		if(type.equals(String.class))
//			return "VARCHAR";
//		else if(type.equals(int.class))
//			return "INT";
//		else if(type.equals(boolean.class))
//			return "BIT";
//			
//		throw new RuntimeException("type not supported - " + type);
//	}

	public String createInsertStatement(Object object) {
		Class<?> c = object.getClass();
		String sql = "INSERT INTO " + c.getSimpleName() + " VALUES (";
		Field[] fields = c.getDeclaredFields();
		
		for(int i = 0; i < fields.length; i++) {
			if(i != 0)
				sql += ",";
			try {
				fields[i].setAccessible(true);
				Object obj = fields[i].get(object);	
				sql += convertToSQL(obj);
				
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		sql += ");";
		return sql;
	}

	private String convertToSQL(Object obj) {
		if(obj.getClass().equals(String.class))
			return "'" + obj.toString() + "'";
		
		return obj.toString();
	}
	
	/*
	 * Contrutores
	 */
	public SQLGenerator(DataMapper mapper) {
		this.mapper = mapper;
	}
	/*
	 *	Atributos
	 */
	private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();
	private DataMapper mapper;
}
